package com.edu.controller;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

@Controller
public class DownloadController {

    /**
     *
     *  通过 使用ServletAPI 进行下载
     *  1其中request对象 用于 获取 要下载文件的 绝对路径
     *  2response对象用于设置响应头，设置下载文件的名称，编码，并设置下载文件的类型，并获取向客户端写回数据的输出流
     *  3通过 io操作，边读边写，把文件复制给客户端实现下载。
     * @param request
     * @param response
     * @throws IOException
     * @throws InterruptedException
     */
    @RequestMapping("/download1")
    public void download1(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
        // 获取请求参数中的文件名
        String fileName = request.getParameter("filename");//也可以是固定文件的下载
        // 构造文件的路径
        String path = "/file/"+fileName;
        // 获取要下载文件的绝对路径
        String realPath = request.getServletContext().getRealPath(path);//获取要下载文件的绝对路径
        // 创建File对象
        File file = new File(realPath);
        // 创建文件输入流
        InputStream ins = new FileInputStream(file);
        // 设置响应头，告诉浏览器以下载附件的形式处理文件，并编码文件名以防止中文名乱码
        response.setHeader("content-disposition","attachment;fileName=" + URLEncoder.encode(file.getName(),"UTF-8"));
        // 获取响应的输出流
        OutputStream oos = response.getOutputStream();
        // 创建缓冲区
        byte[] buffers = new byte[1024];
        int len = 0;
        // 循环读写文件
        while((len = ins.read(buffers))!=-1){
            oos.write(buffers,0,len);
        }
        // 关闭输入流和输出流
        ins.close();
        oos.close();
    }

    /*
     *   基于 Spring提供的 ResponseEntity 进行下载，
     *   ResponseEntity用于表示 返回的实体。
     *   潜在风险：一次性获取 完整的输入流中的数据，有可能造成内存溢出。
     * */

    @RequestMapping("/download2")
    public ResponseEntity<byte[]> download2(HttpServletRequest request,String filename) throws IOException {
        // 构造文件路径
        String path = "/file/"+filename;
        // 获取文件的实际路径
        String realPath = request.getServletContext().getRealPath(path);
        // 创建File对象
        File file = new File(realPath);
        // 初始化HTTP头部信息
        HttpHeaders httpHeaders = new HttpHeaders();
        // 设置内容处置头，用于告知浏览器以附件形式下载文件，并编码文件名以防止中文名乱码
        httpHeaders.set("content-disposition","attachment;fileName=" + URLEncoder.encode(file.getName(),"UTF-8"));
        // 创建文件输入流
        InputStream ins = new FileInputStream(file);
        // 创建字节数组，用于存储文件内容
        byte[] bytes = new byte[ins.available()];
        // 将文件内容读入字节数组
        ins.read(bytes);
        // 关闭文件输入流
        ins.close();
        // 返回包含文件内容、HTTP头部信息和状态码的ResponseEntity对象
        return new ResponseEntity<byte[]>(bytes,httpHeaders, HttpStatus.OK);
    }
}
